#pragma once

#include "v2d.h"
#include "shape.h"
#include "drawing.h"
#include "rect.h"

/** standard Circle using floats */
#define CircleF	Circle<float>
#define recId 2
#define lineId 3

template<typename VTYPE>
class Circle:public Shape<VTYPE>
{
protected:
	/** where this circle is located */
	V2D<VTYPE> m_position;
	/** the radius of the circle */
	VTYPE m_radius;
	int ID;
	int color;
public:

	Circle():m_radius(0){}
	Circle(const V2D<VTYPE> & a_position, const VTYPE & a_radius):m_position(a_position),m_radius(a_radius){}
	inline VTYPE getRadius()const{return m_radius;}
	inline void setRadius(const VTYPE & a_radius){m_radius=a_radius;}
	inline V2D<VTYPE> getPosition()const{return m_position;}
	inline void setPosition(const V2DF & a_position){m_position=a_position;}
	inline void set(const V2D<VTYPE> & a_position, const VTYPE & a_radius)
	{	setPosition(a_position);	setRadius(a_radius);	}
	inline void setColor (const int & a_color)
	{
		color = a_color;
	}
	/** draw this circle */
	void glDraw()const
	{
		glColor3ubv((GLubyte*)&color);
		glDrawCircle((float)m_position.getX(), (float)m_position.getY(), (float)m_radius);}

	/** @return where the position is stored */
	inline V2D<VTYPE> * getPositionAddr(){return &m_position;}
	/** @return where the radius is stored */
	inline VTYPE * getRadiusAddr(){return &m_radius;}
	/** @return true if the given point is within this entity's radius */
	inline bool isWithinRadius(const V2D<VTYPE> & a_point) const
	{
		return m_position.isWithin(m_radius, a_point);
	}
	inline VTYPE getMinY(){return m_position.y-m_radius;}
	inline VTYPE getMaxY(){return m_position.y+m_radius;}
	inline VTYPE getMinX(){return m_position.x-m_radius;}
	inline VTYPE getMaxX(){return m_position.x+m_radius;}
	inline VTYPE getWidth(){return m_radius*2;}
	inline VTYPE getHeight(){return m_radius*2;}

	bool overlaps(const Circle<VTYPE> & c)const
	{return m_position.isWithin(m_radius+c.m_radius, c.m_position);}
	bool collidesWith(const V2D<VTYPE>  mouse)const
	{
		return mouse.isWithin(m_radius,m_position);
	}
	void setID(const int anID)
	{
		ID = anID;
	}
	const int getID() const {return ID;}

	/*bool shapeCollide(const Shape<VTYPE> * colshape) const
	{
		V2D<VTYPE> closestPoint;
		if(colshape->getID() == this->getID())
		{
			Circle<VTYPE> * c = (Circle<VTYPE> *) colshape;
			return overlaps(*c);
		}
		if(colshape->getID() == recId)
		{
			Rect<VTYPE> * r = (Rect<VTYPE> *) colshape;
			V2D<VTYPE> a = V2D<VTYPE>(r->getMinX(), r->getMinY());
			V2D<VTYPE> b = V2D<VTYPE>(r->getMaxX(), r->getMinY());
			V2D<VTYPE> c = V2D<VTYPE>(r->getMaxX(), r->getMaxY());
			V2D<VTYPE> d = V2D<VTYPE>(r->getMinX(), r->getMaxY());
			return (V2D<VTYPE>::lineCrossesCircle(a, b, m_position, m_radius, closestPoint) ||
					 V2D<VTYPE>::lineCrossesCircle(b, c, m_position, m_radius, closestPoint) ||
					 V2D<VTYPE>::lineCrossesCircle(c, d, m_position, m_radius, closestPoint) ||
					 V2D<VTYPE>::lineCrossesCircle(d, a, m_position, m_radius, closestPoint)) ||
					 (r->collidesWith(m_position));
		}
		if(colshape->getID() == lineId)
		{
			Line<VTYPE> * l = (Line<VTYPE> *) colshape;
			V2D<VTYPE> a = l->getA();
			V2D<VTYPE> b = l->getB();
			return (V2D<VTYPE>::lineCrossesCircle(a, b, m_position, m_radius, closestPoint));
		}
	}*/
};
